#ifndef K_STORAGE_H
#define K_STORAGE_H
#pragma once

#include "KList.h"

class KPage;
class KPageList;

class KStorage : KNoCopy {
public:
    explicit KStorage(KPageList *pool = NULL);
    virtual ~KStorage();
public:
    size_t bytesAvailable() const;
    KPageList *poolUsed() const;
public:
    void clear();
    void free();
    bool getChar(char *ch = NULL);
    bool ignore(size_t length);
    bool peek(void *dest, size_t length) const;
    char peekChar() const;
    bool peekChar(char *ch) const;
    bool putChar(char c);
    bool read(void *dest, size_t length);
    bool write(const void *src, size_t length);
    size_t write(KStorage *src, size_t length);
protected:
    virtual KPage *createPage();
private:
    KPage *getPageToWrite();
    static void shift(KList &from, KList &to, bool locked = true);
private:
    KList m_free, m_used;
    KPageList *const m_pool;
    volatile LONG m_bytes;
};

inline size_t KStorage::bytesAvailable() const
{
    return size_t(m_bytes);
}

inline KPageList *KStorage::poolUsed() const
{
    return m_pool;
}

inline bool KStorage::getChar(char *ch)
{
    char c;
    if (read(&c, sizeof c)) {
        if (ch) *ch = c;
        return true;
    }
    return false;
}

inline char KStorage::peekChar() const
{
    char c = '\0';
    peekChar(&c);
    return c;
}

inline bool KStorage::peekChar(char *ch) const
{
    return peek(ch, sizeof(*ch));
}

inline bool KStorage::putChar(char c)
{
    return write(&c, sizeof c);
}

#endif // K_STORAGE_H